home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / pt20pc.zip / BUFFERS.C < prev    next >
Text File  |  1991-02-04  |  10KB  |  355 lines

  1. #include "pt.h"
  2. #include "memory.h"
  3.  
  4. #define hashFn(x,y,z) ((13*(x)+(int)((y)&0x7FFF))%(z))
  5.  
  6. void pascal
  7. /* XTAG:unlink1 */
  8. unlink1(bp)
  9.     register struct diskBuffer *bp;
  10. {
  11.     extern struct diskBuffer *bufHash[];
  12.     
  13.     int h2;
  14.     
  15.     /* unlink it from its old hash chain */
  16.     if( bp->forwardHash != NULL )
  17.         bp->forwardHash->backwardHash = bp->backwardHash;
  18.     if( bp->backwardHash != NULL )
  19.         bp->backwardHash->forwardHash = bp->forwardHash;
  20.     else {    /* first in the hash chain */
  21.         h2 = hashFn(bp->handle, bp->blockNumber, NBUFHASH);
  22.         bufHash[h2] = bp->forwardHash;
  23.     }
  24. }
  25.  
  26. struct diskBuffer * pascal
  27. /* XTAG:getBuffer */
  28. getBuffer(handle, blockNumber)
  29.     int handle;
  30.     long blockNumber;
  31. {
  32.     extern unsigned char msgBuffer[];
  33.     extern struct diskBuffer *buffers;
  34.     extern struct diskBuffer *bufHash[];
  35.     extern int nextBuffer;
  36.     extern struct openFile *files;
  37.     extern int nBuffers;
  38.     extern struct SREGS segRegs;
  39.     extern int addHandle;
  40.     extern int debug;
  41.     extern int maxFiles;
  42.     extern unsigned char *userMessages[];
  43.  
  44.     register int i;
  45.     register struct diskBuffer *bp;
  46.     int h;
  47.     unsigned char far *fp;
  48.     unsigned int bufferBits, fileBits;
  49.  
  50.  
  51.     /* see if the block is already in a buffer */
  52.     h = hashFn(handle, blockNumber, NBUFHASH);
  53.     bp = bufHash[h];
  54.  
  55.     while( bp != NULL ) {
  56.         if( bp->handle==handle && bp->blockNumber==blockNumber ) {
  57.             break;
  58.         }
  59.         bp = bp->forwardHash;
  60.     }
  61.  
  62.     if( bp == NULL ) {
  63.  
  64.         /* if not, assign it a buffer and fill it with data */
  65. /* LATER: use LRU buffer replacment instead of FIFO */
  66.         if( ++nextBuffer >= nBuffers )
  67.             nextBuffer = 0;
  68.         bp = &buffers[nextBuffer];
  69.  
  70.         if( bp->handle != -1 ) {    /* is the buffer in use? */
  71.  
  72.             /* unlink it from its old hash chain */
  73.             unlink1(bp);
  74.  
  75.             /* Invalidate any possible buffer caches. */
  76.             bufferBits = ((unsigned int)FP_OFF(bp->bufferAddress))
  77.                             >> BUFFERSHIFT;
  78.             for(i = 0; i < maxFiles; i++) {
  79.                 /* get the high order bits of the offset */
  80.                 /* of the buffer address */
  81.                 fileBits =
  82.                     ((unsigned int)files[i].logBufOffset)
  83.                             >> BUFFERSHIFT;
  84.                 /* see if the offsets match */
  85.                 if( bufferBits == fileBits ) {
  86.                     /* if so invalidate the cache */
  87.                     files[i].hiLogBuffer = -1L;
  88.                 }
  89.             }
  90.  
  91.             /* write the buffer out to disk */
  92.             if( bp->written ) {
  93.                 lseekls(bp->handle,
  94.                     (bp->blockNumber)<<BUFFERSHIFT, 0);
  95.                 i = writeFar(bp->handle, bp->bufferAddress,
  96.                     BUFFERSIZE);
  97.                 if( i < BUFFERSIZE )
  98.                        msg(userMessages[FULLMSG], 3);
  99.             }
  100.         }
  101.         bp->handle = handle;
  102.         bp->blockNumber = blockNumber;
  103.         bp->written = 0;
  104.  
  105.         /* read in the new buffer contents */
  106.         lseekls(handle, blockNumber<<BUFFERSHIFT, 0);
  107.         i = readFar(handle, bp->bufferAddress, BUFFERSIZE);
  108.         /* read zeros for non-existing chararacters */
  109.         /* this will occur in the add file only */
  110.         if( i <= 0 ) {
  111.             if( i < 0 ) {
  112.                 sprintf(msgBuffer,
  113. "getBuffer: read error, ret=%d, handle=%d", i, handle);
  114.                 msg(msgBuffer, 3);
  115.             }
  116.             /* zero out the buffer */
  117.             fp = bp->bufferAddress;
  118.             for(i = 0; i < BUFFERSIZE; ++i)
  119.                 *fp++ = '\0';
  120.         }
  121.  
  122.         bp->backwardHash = NULL;
  123.         bp->forwardHash = bufHash[h];
  124.         if( bufHash[h] != NULL )
  125.             bufHash[h]->backwardHash = bp;
  126.         bufHash[h] = bp;
  127.     }
  128.     return bp;
  129. }
  130.  
  131. void pascal
  132. /* XTAG:fidInvalid */
  133. fidInvalid(fid)
  134.     int fid;
  135. {
  136.     extern struct diskBuffer *buffers;
  137.     extern int nBuffers;
  138.     extern struct changeItem *change;
  139.     extern int tailChange, nextChange;
  140.     
  141.     register int i;
  142.  
  143.     /* invalidate the buffer cache */
  144.     for(i = 0; i < nBuffers; i++)
  145.         if( buffers[i].handle == fid ) {
  146.             unlink1(&buffers[i]);
  147.             buffers[i].handle = -1;
  148.         }
  149.  
  150.     /* invalidate and history changes that refer to this file */
  151.     i = tailChange;
  152.     if( i != nextChange ) {    /* make sure the history is not empty */
  153.         while( 1 ) {
  154.             if( change[i].fileId==fid && change[i].type!=CNULL) {
  155.                 freePieces( change[i].firstPiece );
  156.                 change[i].type = CNULL;
  157.             }
  158.             if( i == nextChange )
  159.                 break;
  160.             if( ++i >= NHISTORY )
  161.                 i = 0;
  162.         }
  163.     }
  164. }
  165.  
  166. unsigned char pascal
  167. /* XTAG:readChar */
  168. readChar(fileId, logicalByte)
  169.     int fileId;
  170.     long logicalByte;
  171. {
  172.     int n;
  173.     unsigned char far *firstByte;
  174.     unsigned char far *dummy;
  175.     
  176.     n = getSpan(fileId, logicalByte, &firstByte, &dummy, 0);
  177.     if( n != 0 )
  178.         return '\0';
  179.     else
  180.         return *firstByte;
  181. }
  182.  
  183. int pascal
  184. /* XTAG:getSpan */
  185. getSpan(fileId, logicalByte, inFirstByte, inLastByte, reversed)
  186.     int fileId, reversed;
  187.     long logicalByte;
  188.     unsigned char far * *inFirstByte;
  189.     unsigned char far * *inLastByte;
  190. {
  191.     extern unsigned char msgBuffer[];
  192.     extern struct openFile *files;
  193.     extern int debug;
  194.     extern int addHandle;
  195.     extern struct SREGS segRegs;
  196.  
  197.     register struct openFile *ff;
  198.     struct diskBuffer *buf;
  199.     long physicalByte, blockNumber, nn, bp;
  200.     int handle;
  201.     long offset;
  202.     struct piece *pp;
  203.     struct longPointer *firstByte;
  204.     struct longPointer *lastByte;
  205.  
  206.     /* for efficiency, keep some addresses */
  207.     ff = &files[fileId];
  208.     firstByte = (struct longPointer *)inFirstByte;
  209.     lastByte  = (struct longPointer *)inLastByte;
  210.  
  211.     /* if file is not open print an error message */
  212.     if( fileId == -1 || ff->origHandle == -1 ) {
  213.         sprintf(msgBuffer, "getSpan: file %d is not open", fileId);
  214.         msg(msgBuffer, 3);
  215.         return 1;
  216.     }
  217.  
  218.     /* see if the logical byte number is invalid */
  219.     if( logicalByte < 0 || logicalByte >= ff->fileSize)
  220.         return 1;
  221.  
  222.     /* check for optimized special cases */
  223.     if( ff->loLogBuffer<=logicalByte && logicalByte<=ff->hiLogBuffer ) {
  224.         /* if this logical byte is in the buffer cache then set up */
  225.         /* the addresses using the saved segment and offset fields */
  226.         firstByte->offset = ff->logBufOffset
  227.             + (unsigned int)(logicalByte - ff->loLogBuffer);
  228.         if( reversed ) {
  229.             lastByte->offset = firstByte->offset;
  230.             firstByte->offset = ff->logBufOffset;
  231.         } else
  232.             lastByte->offset = ff->logBufOffset
  233.               + (unsigned int)(ff->hiLogBuffer - ff->loLogBuffer);
  234.         firstByte->segment = ff->logBufSegment;
  235.         lastByte->segment = ff->logBufSegment;
  236.         return 0;
  237.     }
  238.  
  239.     /* see if we already know what piece it is in */
  240.     /* findPiece checks this but for speed we do it here anyway */
  241.     /* since readChar is on the critical path of performance */
  242.     if( ff->loLogPiece<=logicalByte && logicalByte<=ff->hiLogPiece ) {
  243.         pp = ff->logPiece;
  244.         physicalByte = pp->position + logicalByte - ff->loLogPiece;
  245.     } else {
  246.         pp = findPiece(logicalByte, ff, &nn);
  247.         physicalByte = pp->position + logicalByte - nn;
  248.         /* remember this piece as the cached piece */
  249.         ff->logPiece = pp;
  250.         ff->loLogPiece = nn;
  251.         ff->hiLogPiece = nn + pp->length - 1;
  252.     }
  253.  
  254.     /* get the physical file block containing this character */
  255.     blockNumber = physicalByte>>BUFFERSHIFT;
  256.  
  257.     /* figure out the appropriate handle */
  258.     if( pp->file == ORIGFILE )
  259.         handle = ff->origHandle;
  260.     else /* pp->file == ADDFILE */
  261.         handle = addHandle;
  262.  
  263.     /* get the buffer that this character is in */
  264.     buf = getBuffer(handle, blockNumber);
  265.  
  266.     /* figure out how many bytes into the buffer logicalByte is */
  267.     offset = physicalByte - (blockNumber<<BUFFERSHIFT);
  268.     firstByte->offset = (char *)FP_OFF(buf->bufferAddress) + offset;
  269.     firstByte->segment = (char *)FP_SEG(buf->bufferAddress);
  270.  
  271.     /* Remember the logical byte limits in this buffer. */
  272.  
  273.     /* Is the beginning of the buffer still in this piece? */
  274.     bp = logicalByte - offset;
  275.  
  276.     /* bp = logical byte number of the first physical byte in buffer */
  277.     /* "buf" ASSUMING all of this buffer is in piece "pp".  Now we */
  278.     /* check this assumption and adjust things if it is false */
  279.  
  280.     if( bp >= ff->loLogPiece ) {
  281.         /* the first byte in this buffer is still in the piece */
  282.         ff->loLogBuffer = bp;
  283.         ff->logBufSegment = (char *)FP_SEG(buf->bufferAddress);
  284.         ff->logBufOffset = (char *)FP_OFF(buf->bufferAddress);
  285.     } else {
  286.         /* the piece begins inside the buffer */
  287.         ff->loLogBuffer = ff->loLogPiece;
  288.         ff->logBufSegment = (char *)FP_SEG(buf->bufferAddress);
  289.         ff->logBufOffset = (char *)FP_OFF(buf->bufferAddress)
  290.                         + (ff->loLogPiece - bp);
  291.     }
  292.  
  293.     /* Now check if the last physical byte in this buffer is still */
  294.     /* in piece "pp" */
  295.  
  296.     /* bp: